"""
实验配置文件 - 用于对比不同架构的性能
"""

# 基础配置
BASE_CONFIG = {
    'graph_hid_dim': 128,
    'q_net_hid_dim': 256,
    'agent_feat_dim': 5,
    'lr': 1e-3,
    'gamma': 0.99,
    'eps_start': 1.0,
    'eps_end': 0.01,
    'eps_decay': 0.995,
    'target_update': 100,
    'use_double_dqn': False,
    'use_dueling': False,
    'use_noisy': False,
    'use_priority_buffer': False
}

# 实验配置组合
EXPERIMENT_CONFIGS = {
    # 1. 基础DQN（对照组）
    'baseline': {
        **BASE_CONFIG,
        'name': 'Baseline DQN',
        'description': '基础DQN，无高级特性'
    },
    
    # 2. 仅添加Double DQN
    'double_dqn': {
        **BASE_CONFIG,
        'use_double_dqn': True,
        'name': 'Double DQN',
        'description': '添加Double DQN技术'
    },
    
    # 3. 仅添加Dueling网络
    'dueling': {
        **BASE_CONFIG,
        'use_dueling': True,
        'name': 'Dueling DQN',
        'description': '添加Dueling网络架构'
    },
    
    # 4. 仅添加Noisy Networks
    'noisy': {
        **BASE_CONFIG,
        'use_noisy': True,
        'eps_start': 0.0,  # Noisy Networks不需要epsilon-greedy
        'eps_end': 0.0,
        'name': 'Noisy Networks',
        'description': '使用Noisy Networks进行探索'
    },
    
    # 5. 仅添加优先级回放
    'priority': {
        **BASE_CONFIG,
        'use_priority_buffer': True,
        'name': 'Priority Replay',
        'description': '使用优先级经验回放'
    },
    
    # 6. Double DQN + Dueling
    'double_dueling': {
        **BASE_CONFIG,
        'use_double_dqn': True,
        'use_dueling': True,
        'name': 'Double + Dueling',
        'description': 'Double DQN与Dueling网络结合'
    },
    
    # 7. Rainbow DQN (所有技术)
    'rainbow': {
        **BASE_CONFIG,
        'use_double_dqn': True,
        'use_dueling': True,
        'use_noisy': True,
        'use_priority_buffer': True,
        'eps_start': 0.0,
        'eps_end': 0.0,
        'lr': 5e-4,  # 更保守的学习率
        'name': 'Rainbow DQN',
        'description': '所有高级技术的组合'
    },
    
    # 8. 大容量网络
    'large_network': {
        **BASE_CONFIG,
        'graph_hid_dim': 512,
        'q_net_hid_dim': 1024,
        'use_double_dqn': True,
        'use_dueling': True,
        'lr': 3e-4,
        'name': 'Large Network',
        'description': '大容量网络架构'
    },
    
    # 9. 快速学习配置
    'fast_learning': {
        **BASE_CONFIG,
        'lr': 5e-3,
        'target_update': 50,
        'eps_decay': 0.99,
        'use_double_dqn': True,
        'name': 'Fast Learning',
        'description': '快速学习配置'
    },
    
    # 10. 保守学习配置
    'conservative': {
        **BASE_CONFIG,
        'lr': 1e-4,
        'target_update': 500,
        'eps_decay': 0.9995,
        'gamma': 0.995,  # 更重视长期奖励
        'use_dueling': True,
        'use_priority_buffer': True,
        'name': 'Conservative Learning',
        'description': '保守学习配置'
    }
}

# 环境配置变体
ENVIRONMENT_CONFIGS = {
    # 简单环境
    'simple': {
        'num_components': 4,
        'max_versions': 6,
        'time_windows': [10, 12, 8],
        'max_parallel': 2,
        'dep_prob': 0.1,
        'name': 'Simple Environment',
        'description': '简单的升级环境'
    },
    
    # 中等复杂度环境
    'medium': {
        'num_components': 6,
        'max_versions': 8,
        'time_windows': [12, 15, 10, 12],
        'max_parallel': 3,
        'dep_prob': 0.2,
        'name': 'Medium Environment',
        'description': '中等复杂度的升级环境'
    },
    
    # 复杂环境
    'complex': {
        'num_components': 8,
        'max_versions': 10,
        'time_windows': [15, 18, 20, 15, 12],
        'max_parallel': 4,
        'dep_prob': 0.3,
        'name': 'Complex Environment',
        'description': '复杂的升级环境'
    },
    
    # 极端复杂环境
    'extreme': {
        'num_components': 12,
        'max_versions': 15,
        'time_windows': [20, 25, 22, 18, 20, 15],
        'max_parallel': 5,
        'dep_prob': 0.4,
        'name': 'Extreme Environment',
        'description': '极端复杂的升级环境'
    }
}

# 训练配置
TRAINING_CONFIGS = {
    'quick_test': {
        'num_episodes': 500,
        'eval_interval': 50,
        'save_interval': 200,
        'name': '快速测试',
        'description': '快速验证模型是否能正常工作'
    },
    
    'standard': {
        'num_episodes': 2000,
        'eval_interval': 100,
        'save_interval': 500,
        'name': '标准训练',
        'description': '标准的训练配置'
    },
    
    'extensive': {
        'num_episodes': 5000,
        'eval_interval': 200,
        'save_interval': 1000,
        'name': '扩展训练',
        'description': '长时间训练以获得最佳性能'
    },
    
    'ablation_study': {
        'num_episodes': 1500,
        'eval_interval': 75,
        'save_interval': 300,
        'name': '消融研究',
        'description': '用于消融研究的训练配置'
    }
}

def get_experiment_config(exp_name):
    """获取实验配置"""
    if exp_name not in EXPERIMENT_CONFIGS:
        raise ValueError(f"未知的实验配置: {exp_name}. 可用配置: {list(EXPERIMENT_CONFIGS.keys())}")
    return EXPERIMENT_CONFIGS[exp_name].copy()

def get_environment_config(env_name):
    """获取环境配置"""
    if env_name not in ENVIRONMENT_CONFIGS:
        raise ValueError(f"未知的环境配置: {env_name}. 可用配置: {list(ENVIRONMENT_CONFIGS.keys())}")
    return ENVIRONMENT_CONFIGS[env_name].copy()

def get_training_config(train_name):
    """获取训练配置"""
    if train_name not in TRAINING_CONFIGS:
        raise ValueError(f"未知的训练配置: {train_name}. 可用配置: {list(TRAINING_CONFIGS.keys())}")
    return TRAINING_CONFIGS[train_name].copy()

def print_all_configs():
    """打印所有可用配置"""
    print("可用的实验配置:")
    print("-" * 50)
    for name, config in EXPERIMENT_CONFIGS.items():
        print(f"{name:15} - {config['description']}")
    
    print("\n可用的环境配置:")
    print("-" * 50)
    for name, config in ENVIRONMENT_CONFIGS.items():
        print(f"{name:15} - {config['description']}")
    
    print("\n可用的训练配置:")
    print("-" * 50)
    for name, config in TRAINING_CONFIGS.items():
        print(f"{name:15} - {config['description']}")

# 推荐的实验组合
RECOMMENDED_EXPERIMENTS = [
    # 基础对比实验
    {
        'experiment': 'baseline',
        'environment': 'medium',
        'training': 'standard',
        'purpose': '建立性能基线'
    },
    {
        'experiment': 'rainbow',
        'environment': 'medium',
        'training': 'standard',
        'purpose': '测试最佳配置'
    },
    
    # 消融研究
    {
        'experiment': 'double_dqn',
        'environment': 'medium',
        'training': 'ablation_study',
        'purpose': '测试Double DQN的效果'
    },
    {
        'experiment': 'dueling',
        'environment': 'medium',
        'training': 'ablation_study',
        'purpose': '测试Dueling网络的效果'
    },
    {
        'experiment': 'noisy',
        'environment': 'medium',
        'training': 'ablation_study',
        'purpose': '测试Noisy Networks的效果'
    },
    {
        'experiment': 'priority',
        'environment': 'medium',
        'training': 'ablation_study',
        'purpose': '测试优先级回放的效果'
    },
    
    # 环境复杂度测试
    {
        'experiment': 'rainbow',
        'environment': 'simple',
        'training': 'quick_test',
        'purpose': '简单环境下的快速验证'
    },
    {
        'experiment': 'rainbow',
        'environment': 'complex',
        'training': 'extensive',
        'purpose': '复杂环境下的性能测试'
    },
    {
        'experiment': 'rainbow',
        'environment': 'extreme',
        'training': 'extensive',
        'purpose': '极限环境下的压力测试'
    }
]

def get_recommended_experiments():
    """获取推荐的实验组合"""
    return RECOMMENDED_EXPERIMENTS.copy()

def validate_config_combination(exp_config, env_config, train_config):
    """验证配置组合的合理性"""
    warnings = []
    
    # 检查学习率和网络大小的匹配
    if exp_config.get('graph_hid_dim', 0) > 256 and exp_config.get('lr', 0) > 1e-3:
        warnings.append("大网络配合高学习率可能导致训练不稳定")
    
    # 检查Noisy Networks和epsilon设置
    if exp_config.get('use_noisy', False) and exp_config.get('eps_start', 0) > 0:
        warnings.append("使用Noisy Networks时建议将epsilon设为0")
    
    # 检查环境复杂度和训练时间
    if env_config.get('num_components', 0) > 10 and train_config.get('num_episodes', 0) < 2000:
        warnings.append("复杂环境可能需要更多训练回合")
    
    # 检查优先级回放和批大小
    if exp_config.get('use_priority_buffer', False) and train_config.get('num_episodes', 0) < 1000:
        warnings.append("优先级回放在训练初期可能效果不明显")
    
    return warnings